/*
————————————————————————————————————————————————————————————————————————————————————
｜ 本文件用于实现拿到各个资源（题目列表、题目的内容、题目的结果）
｜ 设计思路：先描述、再组织！
————————————————————————————————————————————————————————————————————————————————————
*/
#pragma once
#include <iostream>
#include <string>
#include <unordered_map>
#include <algorithm>
#include <fstream>

#include "../Comm/Comm.hpp"
#include "../Comm/Log.hpp"

namespace ns_model
{
    // 题库文件的路径
    const std::string questions_path = "./wwwroot/questions/";
    const std::string ques_list = "ques_lists.txt";
    const std::string message = "message.txt";
    const std::string header = "header.cpp";
    const std::string tail = "tail.cpp";

    // 题目的属性
    struct Question
    {
    public:
        Question(){}
        ~Question(){}
        const Question& operator=(const Question& another)
        {
            if(this != &another)
            {
                _num = another._num;
                _name = another._name;
                _level = another._level;
                _cpu = another._cpu;
                _as = another._as;
                _message = another._message;
                _header = another._header;
                _tail = another._tail;
            }
            return *this;
        }
    public:
        std::string _num;     // 题目编号
        std::string _name;    // 题目名称
        std::string _level;   // 题目难度
        int _cpu;             // 时间要求
        int _as;              // 空间要求
        std::string _message; // 题目的描述文本
        std::string _header;  // 题目的预布置代码
        std::string _tail;    // 题目的测试用例
    };

    class Model
    {
    public:

        Model() 
        {
            GetQuestionAllAttr();
        }
        ~Model() {}

    public:

        // 拿到所有题目的所有属性
        bool GetQuestionAllAttr()
        { 
            // 先读取题目列表
            std::ifstream in(questions_path + ques_list);
            if(!in.is_open()) 
            {
                _log.LogMessage(ClassFile, Error, "打开题目列表文件失败\n");
                return false;
            }
            //一行一行读取
            std::string list_line;
            while(std::getline(in, list_line))
            {   
                Question q;
                std::vector<std::string> vs;
                // 分割
                FileOper::File::SepListLine(list_line, " ", vs);
                if(vs.size() != 5)
                {
                    _log.LogMessage(ClassFile, Error, "加载部分题目失败\n");
                    continue;
                } 

                // 1. 拿到题目的编号
                q._num = vs[0];
                // 2. 拿到题目的名称
                q._name = vs[1];
                // 3. 拿到题目的难度
                q._level = vs[2];
                // 4. 拿到时间要求
                q._cpu = std::stoi(vs[3]);
                // 5. 拿到空间要求
                q._as = std::stoi(vs[4]);
                // 6. 拿到题目的描述文本
                if(!FileOper::File::GetfileMessage(questions_path +  q._num + "/" + message, q._message)) 
                {
                    _log.LogMessage(ClassFile, Error, "获取题目描述文本失败\n");
                    return false;
                }
                // 7. 拿到题目的预布置代码
                if(!FileOper::File::GetfileMessage(questions_path +  q._num + "/" + header, q._header))
                {
                    _log.LogMessage(ClassFile, Error, "获取题目预布置代码失败\n");
                    return false;
                }
                // 8. 拿到题目的测试用例
                if(!FileOper::File::GetfileMessage(questions_path +  q._num + "/" + tail, q._tail))
                {
                    _log.LogMessage(ClassFile, Error, "获取题目测试用例失败\n");
                    return false;
                }
                num_question[q._num] = q;
            }
            in.close();
            _log.LogMessage(ClassFile, Info, "成功获取所有题目的所有属性\n");
            return true;
        }

        // 拿到题库文件的内容 -> 得到题目列表
        bool GetAllQuestions(std::vector<struct Question>& vec_q)
        {
            if(num_question.size() == 0)
            {
                _log.LogMessage(ClassFile, Error, "获取所有题目失败\n");
                return false;
            }
            for(auto& e : num_question)
            {
                vec_q.push_back(e.second);;
            }
            //将题目列表按照题号排序
            std::sort
            (
                vec_q.begin(), 
                vec_q.end(), 
                [](const Question& q1, const Question& q2)
                {
                    return std::stoi(q1._num) < std::stoi(q2._num);
                }
            );
            return true;
        }

        // 拿到题目信息 -> 每个题目的内容
        bool GetQuestionMessage(const std::string &question_number, Question& q)
        {
            const auto& a = num_question.find(question_number);
            if(a == num_question.end()) 
            {
                _log.LogMessage(ClassFile, Error, "当前题目不存在，编号为%s\n", question_number.c_str());
                return false;
            }
            q = a->second;
            return true;
        }

        

    private:
        std::unordered_map<std::string, Question> num_question; // 【编号，属性】      
    };
};